package com.foxchen.ddns.service.impl.v6;

import com.foxchen.ddns.service.IpGetServiceV6;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.Arrays;

@Slf4j
public abstract class V6IpGetAbsService implements IpGetServiceV6 {

    abstract String getProfileActive();

    @Override
    public String getIp(String url) {
        if("iphone".equalsIgnoreCase(getProfileActive())){
            return iphoneDeal(url);
        }

        try {
            log.info("system path:{}",System.getenv("PATH"));

            // 构造命令,iphone比较特殊
            String command = "curl -6 "  + url;
            log.info("command: {}", command);

            // 执行命令
            Process process = Runtime.getRuntime().exec(command);

            // 获取命令执行的结果
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                log.info("command===>{},result: {}",command,line);
                if(StringUtils.isNotBlank(line)){
                    return line;
                }
            }

            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String errorLine;
            while ((errorLine = errorReader.readLine()) != null) {
                log.error("command===>{},error: {}",command,errorLine);
            }
            // 等待命令执行结束
            process.waitFor();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
        return "";
    }

    private String iphoneDeal(String url) {
        try {
            log.info("begin iphone deal,url:{}",url);
            // 解析域名，得到所有的真实ip地址！！！！！
            URI uri = new URI(url);
            String host = uri.getHost();
            InetAddress[] addresses = InetAddress.getAllByName(host);
            log.info("host => addresses:{}",Arrays.toString(addresses));
            InetAddress inetAddressV6 = Arrays
                    .stream(addresses)
                    .filter(inetAddress -> inetAddress instanceof Inet6Address)
                    .findAny()
                    .orElseThrow(() -> new RuntimeException("url: " + url + ",inet6 address not found."));

            // 拿到真实的ipv6地址
            String ipv6Address = inetAddressV6.getHostAddress();
            int port = 443;

            // 1. 忽略证书校验（信任所有证书）
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                    }
            };
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();


            try(Socket socket = new Socket()){
                // 2. 创建 IPv6 连接的 Socket
                InetAddress ipv6 = Inet6Address.getByName(ipv6Address);
                socket.connect(new InetSocketAddress(ipv6, 443), 5000);

                try(SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, host, port, true);
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream(), StandardCharsets.UTF_8));
                    BufferedReader reader = new BufferedReader(new InputStreamReader(sslSocket.getInputStream(), StandardCharsets.UTF_8))){


                    // 3. 将 Socket 升级为 SSLSocket
                    sslSocket.startHandshake();

                    // 4. 手动发送 HTTP 请求，一定要有\r\n，协议规范，代表http请求头结束位标记
                    writer.write("GET /ip HTTP/1.1\r\n");
                    writer.write("Host: " + host + "\r\n");
                    writer.write("User-Agent: JavaCustomClient\r\n");
                    writer.write("Connection: close\r\n");
                    writer.write("\r\n");
                    writer.flush();

                    // 5. 读取响应
                    StringBuilder response = new StringBuilder();
                    String line;
                    String ipV6 = "";
                    while ((line = reader.readLine()) != null) {
                        response.append(line).append("\n");
                        // 最后一行是ipv6
                        ipV6 = line;
                    }
                    log.info("iphone deal,url:{} ===> response:{}",url,response);
                    log.info("iphone deal,url:{} ===> ipV6:{}",url,ipV6);
                    return ipV6;
                }
            }
        } catch (Exception e) {
            log.error("iphone get ipv6 error. url:{}",url,e);
            throw new RuntimeException("iphone get ipv6 error. url:" + url,e);
        }
    }
}
